import type { GreasyForkPageTypeResult, GreasyForkPageTypes } from './types'
import { getCurrentSearch } from '../../../../types/constants'
import { PageRoute } from '../../../abstract/page_route'
import { GreasyForkPageType } from './types'

export class GreasyForkPage extends PageRoute {
  readonly name: string = 'GreasyForkPage'
  private static instance: GreasyForkPage
  get pageType(): GreasyForkPageTypes | 'default' {
    return this.getCurrentPageMeta().type
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): GreasyForkPage {
    if (!GreasyForkPage.instance) {
      GreasyForkPage.instance = new GreasyForkPage()
    }
    return GreasyForkPage.instance
  }

  /**
   * 获取当前页面类型
   */
  public getCurrentPageMeta(): GreasyForkPageTypeResult {
    const url = this.getCurrentUrl()
    const path = new URL(url).pathname
    const langPrefix = this.getLanguagePrefix(path)
    const basePath = path.replace(new RegExp(`^/${langPrefix}`), '')

    // 404 页面检测
    const notFoundResult = this.detectNotFoundPage()
    if (notFoundResult)
      return notFoundResult

    // 首页
    if (/^\/?$/.test(basePath)) {
      return { type: GreasyForkPageType.INDEX }
    }

    // 登录相关页面检测
    const signResult = this.detectSignPages(basePath)
    if (signResult)
      return signResult

    // 脚本详情相关页面检测
    const scriptResult = this.detectScriptPages(basePath)
    if (scriptResult)
      return scriptResult

    // 用户相关页面检测
    const userResult = this.detectUserPages(basePath)
    if (userResult)
      return userResult

    // 讨论相关页面检测
    const discussionResult = this.detectDiscussionPages(basePath)
    if (discussionResult)
      return discussionResult

    // 帮助页
    const helpResult = this.detectHelpPages(basePath)
    if (helpResult)
      return helpResult

    // 其他功能页面检测
    const otherResult = this.detectOtherPages(basePath)
    if (otherResult)
      return otherResult

    return { type: 'default' }
  }

  /**
   * 检测登录相关页面
   */
  private detectSignPages(basePath: string): GreasyForkPageTypeResult | null {
    // 登录相关页
    const signMatch = basePath.match(/^\/users\/(sign_in|sign_up|sign_out)(?:\/?|\?.*)$/)
    if (signMatch) {
      const subPage = signMatch[1]

      const signPageMap: Record<string, GreasyForkPageType> = {
        sign_up: GreasyForkPageType.SIGN_UP,
        sign_in: GreasyForkPageType.SIGN_IN,
        sign_out: GreasyForkPageType.SIGN_OUT,
      }

      const pageType = signPageMap[subPage]

      if (!pageType)
        return null

      return {
        type: pageType,
      }
    }

    return null
  }

  /**
   * 检测脚本相关页面
   */
  private detectScriptPages(basePath: string): GreasyForkPageTypeResult | null {
    const scriptMatch = basePath.match(/^\/scripts\/(\d+)(?:-[^/]+)?(?:\/([^/?#]+)(?:\/(\d+|new))?)?/)

    if (!scriptMatch)
      return null

    const scriptId = scriptMatch[1]
    const subPage = scriptMatch[2]
    const subPath = scriptMatch[3]

    const typeMap: Record<string, GreasyForkPageType> = {
      info: GreasyForkPageType.SCRIPT_INFO,
      code: GreasyForkPageType.SCRIPT_CODE,
      versions: subPath === 'new'
        ? GreasyForkPageType.SCRIPT_VERSIONS_NEW
        : GreasyForkPageType.SCRIPT_VERSIONS,
      feedback: GreasyForkPageType.SCRIPT_FEEDBACK,
      stats: GreasyForkPageType.SCRIPT_STATS,
      derivatives: GreasyForkPageType.SCRIPT_DERIVATIVES,
      delete: GreasyForkPageType.SCRIPT_DELETE,
      admin: GreasyForkPageType.SCRIPT_ADMIN,
      discussions: GreasyForkPageType.SCRIPT_DISCUSSION,
      diff: GreasyForkPageType.SCRIPT_DIFF,
      script_lock_appeals: GreasyForkPageType.SCRIPT_LOCK_APPEALS,
    }

    const type = typeMap[subPage]
    const discussionId = subPath === 'new' ? undefined : subPath

    // 脚本删除页检测
    if (!type) {
      const isDeleted = this.isScriptDeletedPage()
      if (isDeleted) {
        return {
          type: GreasyForkPageType.SCRIPT_DELETED,
          scriptId,
          discussionId,
        }
      }
    }

    return {
      type: type || GreasyForkPageType.SCRIPT_INFO,
      scriptId,
      discussionId,
    }
  }

  /**
   * 检测用户相关页面
   */
  private detectUserPages(basePath: string): GreasyForkPageTypeResult | null {
    // 用户个人资料页
    const userProfileMatch = basePath.match(/^\/users\/(\d+)(?:-[^/]+)?(?:\/([^/?#]+(?:\/[^/?#]+)?))?\/?$/)
    if (userProfileMatch) {
      const userId = userProfileMatch[1]
      const subPage = userProfileMatch[2]

      const userPageMap: Record<string, GreasyForkPageType> = {
        'sets': GreasyForkPageType.SETS_NEW,
        'sets/new': GreasyForkPageType.SETS_NEW,
        'notifications': GreasyForkPageType.NOTIFICATIONS,
        'notification_settings': GreasyForkPageType.NOTIFICATION_SETTINGS,
        'conversations/new': GreasyForkPageType.USER_CONVERSATIONS,
        '': GreasyForkPageType.USER_PROFILE, // 默认用户资料页
      }

      const pageType = subPage ? userPageMap[subPage] : GreasyForkPageType.USER_PROFILE

      if (!pageType)
        return null

      return {
        type: pageType,
        userId,
      }
    }

    const userMatch = basePath.match(/^\/users\/([^/?#]+)\/?$/)
    if (userMatch) {
      const pageName = userMatch[1]

      const userPageMap: Record<string, GreasyForkPageType> = {
        'edit': GreasyForkPageType.EDIT,
        'webhook-info': GreasyForkPageType.WEBHOOK_INFO,
        'edit_sign_in': GreasyForkPageType.EDIT_SIGN_IN,
        'delete_info': GreasyForkPageType.DELETE_INFO,
        'sign_out': GreasyForkPageType.SIGN_OUT,
        '': GreasyForkPageType.USER_PROFILE, // 默认用户资料页
      }

      const pageType = pageName ? userPageMap[pageName] : GreasyForkPageType.USER_PROFILE

      if (!pageType)
        return null

      return {
        type: pageType,
      }
    }

    // 用户列表页
    if (/^\/users\/?(?:\?.*)?$/.test(basePath)) {
      return { type: GreasyForkPageType.USERS }
    }

    return null
  }

  /**
   * 检测讨论相关页面
   */
  private detectDiscussionPages(basePath: string): GreasyForkPageTypeResult | null {
    const discussionMatch = basePath.match(/^\/discussions(?:\/([^/?#]+))?(?:\/(\d+)(?:-[^/?#]+)?)?\/?$/i)

    if (!discussionMatch)
      return null

    const [_, category, discussionId] = discussionMatch

    if (discussionId) {
      return {
        type: GreasyForkPageType.DISCUSSIONS_DETAIL,
        discussionId,
      }
    }

    const DiscussionPageMap: Record<string, GreasyForkPageType> = {
      'new': GreasyForkPageType.DISCUSSIONS_NEW,
      'greasyfork': GreasyForkPageType.DISCUSSIONS_GREASY_FORK,
      'development': GreasyForkPageType.DISCUSSIONS_DEVELOPMENT,
      'requests': GreasyForkPageType.DISCUSSIONS_REQUESTS,
      'script-discussions': GreasyForkPageType.DISCUSSIONS_SCRIPT,
      'no-scripts': GreasyForkPageType.DISCUSSIONS_NO_SCRIPT,
    }

    const pageType = category ? DiscussionPageMap[category] : GreasyForkPageType.DISCUSSIONS

    if (!pageType)
      return null

    return {
      type: pageType,
      ...(category ? { siteDomain: category } : {}),
    }
  }

  /**
   * 检测帮助相关页面
   */
  private detectHelpPages(basePath: string): GreasyForkPageTypeResult | null {
    // 帮助页
    const helpMatch = basePath.match(/^\/help(?:\/([^/?#]+))?\/?$/)
    if (helpMatch) {
      const helpPage = helpMatch[1]

      const helpPageMap: Record<string, GreasyForkPageType> = {
        '': GreasyForkPageType.HELP,
        'allowed-markup': GreasyForkPageType.ALLOWED_MARKUP,
        'code-rules': GreasyForkPageType.CODE_RULES,
        'contact': GreasyForkPageType.CONTACT,
        'credits': GreasyForkPageType.CREDITS,
        'external-scripts': GreasyForkPageType.EXTERNAL_SCRIPTS,
        'installing-user-scripts': GreasyForkPageType.INSTALLING_USER_SCRIPTS,
        'installing-user-styles': GreasyForkPageType.INSTALLING_USER_STYLES,
        'meta-keys': GreasyForkPageType.META_KEYS,
        'privacy': GreasyForkPageType.PRIVACY,
        'rewriting': GreasyForkPageType.REWRITING,
        'user-js-conversions': GreasyForkPageType.USER_JS_CONVERSIONS,
        'writing-user-scripts': GreasyForkPageType.WRITING_USER_SCRIPTS,
      }

      const pageType = helpPage ? helpPageMap[helpPage] : GreasyForkPageType.HELP

      if (!pageType)
        return null

      return {
        type: pageType,
        siteDomain: helpPage,
      }
    }

    return null
  }

  /**
   * 检测其他功能页面
   */
  private detectOtherPages(basePath: string): GreasyForkPageTypeResult | null {
    const pageDetectors: Array<[RegExp, (...args: any[]) => GreasyForkPageTypeResult]> = [
      // 新密码
      [/^\/users\/password\/new\/?$/, () => {
        return { type: GreasyForkPageType.PASSWORD_NEW }
      }],

      // 密码修改页
      [/^\/users\/password\/edit\/?$/, () => {
        return { type: GreasyForkPageType.PASSWORD_EDIT }
      }],

      // 脚本列表页
      [/^\/scripts\/?$/, () => {
        return { type: GreasyForkPageType.SCRIPT_LIST }
      }],

      // 按站点分类的脚本列表页
      [/^\/scripts\/by-site\/([^/?#]+)/, (match: RegExpMatchArray) => {
        return {
          type: GreasyForkPageType.SCRIPT_LIST,
          siteDomain: match[1],
        }
      }],

      // 导入脚本页
      [/^\/import\/?$/, () => {
        return { type: GreasyForkPageType.IMPORT }
      }],

      [/^\/script_versions\/new\/?$/, () => {
        // 解析URL参数
        const urlParams = new URLSearchParams(getCurrentSearch())
        const language = urlParams.get('language')

        // 根据 language 参数确定页面类型
        if (language === 'css') {
          // 新建样式页
          return { type: GreasyForkPageType.NEW_CSS }
        }

        // 新建脚本页
        return { type: GreasyForkPageType.NEW_JS }
      }],

      // 搜索页
      [/^\/search\/?$/, () => {
        return { type: GreasyForkPageType.SEARCH }
      }],

      // 审核操作页
      [/^\/moderator_actions\/?$/, () => {
        return { type: GreasyForkPageType.MODERATOR_ACTIONS }
      }],

      // 报告页
      [/^\/reports(?:\/\d+)?\/?$/, () => {
        return { type: GreasyForkPageType.REPORTS }
      }],

      // 报告新建页
      [/^\/reports\/new\/?$/, () => {
        return { type: GreasyForkPageType.REPORTS_NEW }
      }],

      // 库页
      [/^\/scripts\/libraries\/?$/, () => {
        return { type: GreasyForkPageType.LIBRARIES }
      }],

      // 站点分类页
      [/^\/scripts\/by-site\/?$/, () => {
        return { type: GreasyForkPageType.BY_SITE }
      }],
    ]

    for (const [regex, handler] of pageDetectors) {
      const match = basePath.match(regex)
      if (match) {
        return handler(match)
      }
    }

    return null
  }

  /**
   * 检测 404 页面
   */
  private detectNotFoundPage(): GreasyForkPageTypeResult | null {
    const pageNotFoundRules = [
      /404.*Page Not Found/i, // 不区分大小写
      /404.*未找到此页/,
    ]

    if (pageNotFoundRules.some(regex => regex.test(document.title))) {
      return { type: GreasyForkPageType.NOT_FOUND }
    }

    return null
  }

  /**
   * 检测是否为脚本删除页面
   */
  private isScriptDeletedPage(): boolean {
    const DELETED_SCRIPT_MESSAGES = [
      { text: '此脚本已因此举报被删除', lang: 'zh-CN' },
      { text: 'This script has been deleted due to this report.', lang: 'en' },
    ]

    const UNUSED_SCRIPT_MESSAGES = [
      { text: '此脚本不再在本网站上可用', lang: 'zh-CN' },
      { text: 'This script is no longer available on this site', lang: 'en' },
    ]

    const pageContent = $('.text-content').text()

    const isScriptDeleted = DELETED_SCRIPT_MESSAGES.some(
      message => pageContent.includes(message.text),
    )
    const isUnusedScript = UNUSED_SCRIPT_MESSAGES.some(
      message => pageContent.includes(message.text),
    )

    return isScriptDeleted || isUnusedScript
  }

  /**
   * 获取语言前缀 (zh-CN, en 等)
   */
  private getLanguagePrefix(path: string): string {
    const langMatch = path.match(/^\/([a-z]{2}(?:-[A-Z]{2})?)/)
    return langMatch ? langMatch[1] : ''
  }
}
